﻿using System;
using System.Collections.Generic;
using Castle.DynamicProxy;

namespace Accona.Remoting.Remoting
{
    public class RemoteCallInterceptor : IInterceptor
    {
        private readonly Guid applicationId;
        private readonly ISender sender;
        private readonly IServiceLookup serviceLookup;
        private readonly WaiterQueue waiterQueue;


        public RemoteCallInterceptor(Guid applicationId, ISender sender, WaiterQueue waiterQueue,
                                     ServiceLookup serviceLookup)
        {
            this.applicationId = applicationId;
            this.sender = sender;
            this.waiterQueue = waiterQueue;
            this.serviceLookup = serviceLookup;
        }

        #region IInterceptor Members

        public void Intercept(IInvocation invocation)
        {
            Guid callId = Guid.NewGuid();
            IList<ServiceInfo> availibleServices = serviceLookup.LookupServices(invocation.Method.DeclaringType);
            if (availibleServices == null || availibleServices.Count == 0)
                throw new NoAvalibleServiceException(invocation.Method.DeclaringType);
            byte[] serializedMethod = new MethodSerializer(applicationId).SerializeMethodCall(invocation.Method,
                                                                                              invocation.Arguments, true,
                                                                                              callId,
                                                                                              availibleServices[0]);
            if (!invocation.Method.ReturnType.Equals(typeof (void)))
            {
                object result = waiterQueue.Query(sender, serializedMethod, 30000, callId);
                invocation.ReturnValue = result;
            }
            else
                sender.Send(serializedMethod);
        }

        #endregion
    }
}